/**
 * 
 */
package com.shark.app.persistent.aop;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.reflect.MethodSignature;
import org.shark.jdbcTemplateTool.utils.sql.SqlLoadFactory;
import org.springframework.data.repository.query.Param;

import com.google.common.collect.Maps;

/**
 * @author lenovo
 * @description
 * @date 2016年8月18日
 */
public class SqlContentManagerAop {

	private static Map<Method, String> map = Maps.newConcurrentMap();

	@Around("execution(* com.shark.app.persistent.dao..*.*(..))")
	public Object getSqlByMethod(ProceedingJoinPoint pjp) throws Throwable {

		Signature signature = pjp.getSignature();
		Method targetMethod = ((MethodSignature)signature).getMethod();
		Method realMethod = pjp.getTarget().getClass().getMethod(signature.getName(),
				targetMethod.getParameterTypes());
		String sql = map.get(realMethod);

		// Sql 没有被缓存过
		if (StringUtils.isBlank(sql)) {
			String key = "";
			String className = targetMethod.getDeclaringClass().getName();
			key = className + "." + targetMethod.getName();
			sql = SqlLoadFactory.getInstant().getLoad().getSql(key);
			if (StringUtils.isBlank(sql)) {
				return pjp.proceed();
			}
			map.put(realMethod, sql);
		}

		// 没有参数
		if (pjp.getArgs().length == 0) {
			return pjp.proceed();
		}

		Map<String, Object> paramMap = Maps.newHashMap();
		int index = 0;
		Annotation[][] paramsAnnos = realMethod.getParameterAnnotations();
		for (Annotation[] paramAnnos : paramsAnnos) {
			for (Annotation a : paramAnnos) {
				if (a instanceof Param) {
					paramMap.put(((Param) a).value(), pjp.getArgs()[index]);
				}
			}
			index ++;
		}
		
		Method setSqlMethod = pjp.getTarget().getClass().getMethod("setSql", String.class);
		Method setparamMethod = pjp.getTarget().getClass().getMethod("setParams", Map.class);
		setSqlMethod.invoke(pjp.getTarget(), sql);
		setparamMethod.invoke(pjp.getTarget(), paramMap);
		return pjp.proceed();
	}
}
